import random
from unittest import result
from main import mongo_client, insert_batch_data
from datetime import datetime, timedelta
from pymongo import UpdateOne
from tqdm import tqdm
from faker import Faker
from bson.objectid import ObjectId
import get_data 
import sys
import json


fake = Faker()

def get_value(dic, key):
    '''
    判断字典是否存在key, 存在则返回对应value, 不存在则返回0
    '''
    return dic[key] if key in dic else 0


def get_time(year: int, month: int, day: int):
    '''
    构造查询时间
    input:查询具体时间，年月日
    output:查询开始时间和结束时间
    '''
    # 构造查询时间
    date_to_query = datetime(year=year, month=month, day=day)
    # 创建当天开始和结束的时间对象
    start_of_day = datetime(
        date_to_query.year, date_to_query.month, date_to_query.day)
    end_of_day = datetime(date_to_query.year,
                          date_to_query.month, date_to_query.day, 23, 59, 59)
    return start_of_day, end_of_day

def get_rate(up, down):
    if not down:
        return 0.0000
    r = up/down
    return f"{r:.4f}"

def search_otherDay_total_data(start_time: datetime, end_time: datetime, mongo_collection):
    '''
    查询数据及总数
    input:查询开始和结束时间, MongoDB数据库
    output:查询到的数据及总数量
    '''
    # 查询到的数据
    doc_hits = mongo_collection.find({
        'atime': {
            '$gte': start_time,
            '$lte': end_time
        }
    })
    # 查询到的数据总数量
    total_hits = mongo_collection.count_documents({
        'atime': {
            '$gte': start_time,
            '$lte': end_time
        }
    })
    return total_hits, doc_hits


def search_data(start_time: datetime, end_time: datetime, mongo_collection, search_code=0):
    '''
    查询指定时间段内的各个组件的对应数据
    input:
    查询的开始和结束时间, MongoDB数据库, 
    search_code: 查询代码,默认查询数据量统计数据,设置为1表示查询数据量的独立用户数
    output:
    字典, key(oid)-vlaue(data_count|unique_user_count)
    '''
    # 构造查询条件
    # 数据量统计查询条件,指定集合中的一段时间内oid出现的次数
    count_pipeline = [
        {
            '$match': {
                'atime': {
                    '$gte': start_time,
                    '$lte': end_time
                }
            }
        },
        {
            "$group": {
                '_id': '$oid',
                'count': {'$sum': 1}
            },
        }
    ]
    # 独立用户数查询条件， 
    unique_user_pipeline = [
        {
            '$match': {
                'atime': {
                    '$gte': start_time,
                    '$lte': end_time
                }
            }
        },
        {
            '$group': {
                '_id': {
                    'oid': '$oid',
                    'open_id': '$open_id'  # 按oid和open_id组合分组
                }
            }
        },
        {
            '$group': {
                '_id': '$_id.oid',  # 使用上一个分组的oid作为新的分组依据
                'count': {'$sum': 1}  # 计算每个oid的唯一用户数
            }
        }
    ]

    # 执行聚合查询(去重后的数据统计)
    if search_code == 0:
        # 统计量数据的查询
        records = list(mongo_collection.aggregate(count_pipeline))
        # 查询到的数据总数
        total_hits = mongo_collection.count_documents({
            'atime': {
                '$gte': start_time,
                '$lte': end_time
            }})
    elif search_code == 1:
        # 统计量独立用户数的查询
        records = list(mongo_collection.aggregate(unique_user_pipeline))
        total_hits = 0
    de_duplicate_results = {}
    for f in records:
        oid = f['_id']
        data_count = f['count']
        de_duplicate_results[oid] = data_count
    return de_duplicate_results, total_hits


def combine_data(view_count_dict: dict, view_user_dict: dict, click_count_dict: dict, click_user_dict: dict, complete_set_count_dict: dict, complete_set_user_dict: dict) -> dict:
    '''
    将字典中的数据组合在一起。
    input:
        {'oid':-,'view':view}
        {'oid':-,'click':click}
        {'oid':-,'complete':complete}
        ...
    output:
    {
        'oid':[view, click, complete],
        ......
    }
    '''
    # 遍历完成设置量的 oid
    print('开始组合数据：')
    result_dict = {}
    progress_bar = tqdm(desc='组合数据', unit='条')
    for key, complete_set_value in complete_set_count_dict.items():
        lis = []
        complete_set_user_value = get_value(
            dic=complete_set_user_dict, key=key)
        click_value = get_value(dic=click_count_dict, key=key)
        click_user_value = get_value(dic=click_user_dict, key=key)
        view_value = get_value(dic=view_count_dict, key=key)
        view_user_value = get_value(dic=view_user_dict, key=key)
        lis.append(view_value)
        lis.append(view_user_value)
        lis.append(click_value)
        lis.append(click_user_value)
        lis.append(complete_set_value)
        lis.append(complete_set_user_value)
        result_dict[key] = lis
        progress_bar.update(1)  # 更新进度条

    # 遍历其他 oid
    for key, view_value in view_count_dict.items():
        if key in result_dict:
            continue
        lis = []
        complete_set_value = 0
        complete_set_user_value = 0
        view_user_value = get_value(dic=view_user_dict, key=key)
        click_value = get_value(dic=click_count_dict, key=key)
        click_user_value = get_value(dic=click_user_dict, key=key)
        lis.append(view_value)
        lis.append(view_user_value)
        lis.append(click_value)
        lis.append(click_user_value)
        lis.append(complete_set_value)
        lis.append(complete_set_user_value)
        result_dict[key] = lis
        progress_bar.update(1)  # 更新进度条
    progress_bar.close()  # 关闭进度条
    print('完成组合')
    return result_dict


def insert_user_data(start_time: datetime, end_time: datetime, mongo_client, batch_size=10000):
    '''
    插入用户组件交互数据
    input:查询开始和结束时间, MongoDB数据库
    '''

    view_collection = mongo_client['novapps_server']['ios_widget_analysis_widget_view']
    click_collection = mongo_client['novapps_server']['ios_widget_analysis_widget_click']
    complete_set_collection = mongo_client['novapps_server']['ios_widget_analysis_widget_complete_set']
    user_widget_collection = mongo_client['novapps_server']['ios_widget_analysis_user_widget']
    print('*'*40+f'{start_time.date()}'+'*'*40)
    print('开始查询数据：')

    complete_set_count_dict, complete_set_total_hits = search_data(
        start_time=start_time, end_time=end_time, mongo_collection=complete_set_collection)
    print(f'完成设置量数据共：{complete_set_total_hits}条')
    view_count_dict, view_total_hits = search_data(
        start_time=start_time, end_time=end_time, mongo_collection=view_collection)
    print(f'展示量数据共：{view_total_hits}条')

    if len(view_count_dict) == 0 and len(complete_set_count_dict) == 0:
        print(f'{start_time.date()}没有数据')
        return

    if not complete_set_count_dict:
        complete_set_count_dict = {}
    else:
        complete_set_count_user_dict, _ = search_data(
            start_time=start_time, end_time=end_time, mongo_collection=complete_set_collection, search_code=1)
        print(f'完成设置量的组件数:{len(complete_set_count_user_dict)}')

    if not view_count_dict:
        click_count_dict = {}
        click_count_user_dict = {}
        view_count_user_dict = {}
    else:
        view_count_user_dict, _ = search_data(
            start_time=start_time, end_time=end_time, mongo_collection=view_collection, search_code=1)
        print(f'展示量的组件数:{len(view_count_dict)}')
        click_count_dict, click_total_hits = search_data(
            start_time=start_time, end_time=end_time, mongo_collection=click_collection)
        print(f'点击量数据共：{click_total_hits}条')
        click_count_user_dict, _ = search_data(
            start_time=start_time, end_time=end_time, mongo_collection=click_collection, search_code=1)
        print(f'点击量的组件数:{len(click_count_user_dict)}')

    print('完成查询')

    # 合并数据
    count_dict = combine_data(view_count_dict=view_count_dict,
                              view_user_dict=view_count_user_dict,
                              click_count_dict=click_count_dict,
                              click_user_dict=click_count_user_dict,
                              complete_set_count_dict=complete_set_count_dict,
                              complete_set_user_dict=complete_set_count_user_dict)

    result_list = []
    for key, value in count_dict.items():
        post_data = {
            'atime': start_time,
            'oid': key,
            'view_count': value[0],
            'view_count_user': value[1],
            'click_count': value[2],
            'click_count_user': value[3],
            'complete_set_count': value[4],
            'complete_set_count_user': value[5],
        }
        result_list.append(post_data)

    total = len(result_list)
    # 批量插入数据
    for i in range(0, total, batch_size):
        batch = result_list[i:i+batch_size]
        user_widget_collection.bulk_write([
            UpdateOne(
                {'oid': document['oid']},
                {'$set': document},
                upsert=True
            )
            for document in batch
        ])
        print(
            f'Inserted batch {i//batch_size + 1}/{(total // batch_size) + 1}')
    print(f"用户组件交互数据库完成插入{total}条数据")

# 测试
def test_data(code=1):
    if code == 1:
        # start_time, end_time = get_time(2023, 12, 18)
        # insert_user_data(start_time=start_time, end_time=end_time, mongo_client=mongo_client)
        start_datetime = datetime(2023, 12, 1, 0, 0, 0)
        end_datetime = datetime(2023, 12, 20, 23, 59, 59)
        module_list_col = mongo_client['novapps_server']['ios_widget_component_library_module_list']
        results = module_list_col.find({},{'_id':1,'atime':1})
        for f in results:
            # view_count = random.randint(1,60)
            # click_count = random.randint(1,view_count)
            # complete_set_count = random.randint(1,click_count)
            # post_data = {
            #     'atime': fake.date_time_between(start_date=start_datetime, end_date=end_datetime),
            #     'oid': f['_id'],
            #     'view_count': view_count,
            #     'view_count_user': random.randint(1,view_count),
            #     'click_count': click_count,
            #     'click_count_user': random.randint(1,click_count),
            #     'complete_set_count': complete_set_count,
            #     'complete_set_count_user': random.randint(1,complete_set_count),
            #     'click_rate': get_rate(click_count, view_count),
            #     'complete_set_rate': get_rate(complete_set_count, click_count)
            # }
            # user_col.insert_one(post_data)
            print(f['_id'])


        # result = get_data.get_analysis_data(start_date=start_time, end_date=end_time)
        # for f in result['res']:
        #     print(f)



    elif code == 2:
        current_time = datetime.now()
        for f in range(1, 31):  # 同步 31 天
            past_day = current_time - timedelta(days=f)
            year = past_day.year
            month = past_day.month
            day = past_day.day
            start_time, end_time = get_time(year, month, day)
            insert_user_data(start_time=start_time,
                                end_time=end_time, mongo_client=mongo_client)
    else:
        print("None")

if __name__ == "__main__":
    user_col = mongo_client['novapps_server']['ios_widget_analysis_user_widget']
    user_col.drop()


    # test_data()

    # with open('output.txt', 'a') as f:
    #     original_stdout = sys.stdout
    #     sys.stdout = f  # 将标准输出重定向到文件
    #     print(f'\n[INFO: {datetime.now()}]')
    #     # print()
    #     test_data()
    #     sys.stdout = original_stdout
